/*
 ============================================================================
 Name		 : ContactEngine.cpp
 Author	     : jshuabo.com
 Version	 : 1.0
 Copyright   : jshuabo.com,All Right Reserved!
 Description : CContactEngine implementation
 ============================================================================
 */
#include <CNTDB.H>
#include <CNTFLDST.H>
#include <utf.h>
#include <CNTFLDST.H>

#include "ContactEngine.h" 
#include "TContactItemID.h"


#ifdef WRITE_TO_LOG

_LIT(KSeprate,",");
_LIT(KContactSeprate,"\r\n");

_LIT8(KEnter,"\r\n");
_LIT8(KFieldText,"FieldText==");
_LIT8(KLabel,"Label==");

_LIT(KTestLabel,"Test Label");
_LIT(KFileName,"C:\\CELog.txt");

#endif



//consts
_LIT(KContactItemSeprate,",");
_LIT(KHeadFile,"C:\\ExportHead.txt");
const TInt KSeprateLength = 2;


ContactEngine::ContactEngine()
{	 
	iContactsDb = NULL;
	iExportingNotify = NULL;
	iHeadText = NULL;
}

ContactEngine::~ContactEngine()
{
	if(iContactsDb)
	{
		delete iContactsDb;
		iContactsDb = NULL;
	}
	if(iHeadText)
	{
		delete iHeadText;
		iHeadText = NULL;
	}
	iContactArray.ResetAndDestroy();
	iContactArray.Close();
	
	iContactIdArray.ResetAndDestroy();
	iContactIdArray.Close();
}

ContactEngine* ContactEngine::NewLC(MContactExportingNotify* aContactExportingNotify)
{
	ContactEngine* self = new (ELeave) ContactEngine();
	CleanupStack::PushL(self);
	self->ConstructL(aContactExportingNotify);
	return self;
}

ContactEngine* ContactEngine::NewL(MContactExportingNotify* aContactExportingNotify)
{
	ContactEngine* self = ContactEngine::NewLC(aContactExportingNotify);
	CleanupStack::Pop(); // self;
	return self;
}

void ContactEngine::ConstructL(MContactExportingNotify* aContactExportingNotify)
{
	InitializeContactItemID();
	ExportingContactsToArray(); 
	iExportingNotify = aContactExportingNotify;
	iHeadText = ReadHeadText(KHeadFile);
}

void ContactEngine::InitializeContactItemID()
{
	TContactItemID* pTempContactItemID = NULL;		
	
	//FamilyName and GivenName
	for(TInt item = 0;item<2;item++)
	{
		pTempContactItemID = new(ELeave) TContactItemID();
		pTempContactItemID->iMainValue = KUidContactFieldFamilyNameValue-item ;	
		pTempContactItemID->iItemIDCount = 1;
		iContactIdArray.Append(pTempContactItemID);	 
	}
	
	//Mobile
	pTempContactItemID = new(ELeave) TContactItemID();
	pTempContactItemID->iMainValue = KUidContactFieldPhoneNumberValue;
	pTempContactItemID->iVCardMapPropertyValue = KIntContactFieldVCardMapCELL;
	pTempContactItemID->iItemIDCount = 2;
	iContactIdArray.Append(pTempContactItemID);	 
	
	//FamilyPhone and WorkPhone
	for(TInt item = 0;item<2;item++)
	{
		pTempContactItemID = new(ELeave) TContactItemID();
		pTempContactItemID->iMainValue = KUidContactFieldPhoneNumberValue;
		pTempContactItemID->iVCardMapPropertyValue = KIntContactFieldVCardMapVOICE;
		pTempContactItemID->iVCardMapPlaceValue = KIntContactFieldVCardMapHOME-item;
		pTempContactItemID->iItemIDCount = 3;
		iContactIdArray.Append(pTempContactItemID);	 
	}	
	
	//Familyfax and Workfax 
	for(TInt item = 0;item<2;item++)
	{
		pTempContactItemID = new(ELeave) TContactItemID();
		pTempContactItemID->iMainValue = KUidContactFieldFaxValue;
		pTempContactItemID->iVCardMapPropertyValue = KIntContactFieldVCardMapFAX;
		pTempContactItemID->iVCardMapPlaceValue = KIntContactFieldVCardMapHOME-item;
		pTempContactItemID->iItemIDCount = 3;
		iContactIdArray.Append(pTempContactItemID);	
	}
	
	//Other phone
	pTempContactItemID = new(ELeave) TContactItemID();
	pTempContactItemID->iMainValue = KUidContactFieldPhoneNumberValue;
	pTempContactItemID->iVCardMapPropertyValue = KIntContactFieldVCardMapVOICE;
	pTempContactItemID->iItemIDCount = 2;
	iContactIdArray.Append(pTempContactItemID);	
	
	//FamilyEmail and WorkEmail
	for(TInt item = 0;item<2;item++)
	{
		pTempContactItemID = new(ELeave) TContactItemID();
		pTempContactItemID->iMainValue = KUidContactFieldEMailValue;
		pTempContactItemID->iVCardMapPlaceValue = KIntContactFieldVCardMapHOME - item;
		pTempContactItemID->iItemIDCount = 2;
		iContactIdArray.Append(pTempContactItemID);	
	}
	
	//other Email
	pTempContactItemID = new(ELeave) TContactItemID();
	pTempContactItemID->iMainValue = KUidContactFieldEMailValue;
	pTempContactItemID->iItemIDCount = 1;
	iContactIdArray.Append(pTempContactItemID);	
	
	//Familly Address
	for(TInt item = 0;item<5;item++)
	{
		pTempContactItemID = new(ELeave) TContactItemID();
		pTempContactItemID->iMainValue = KUidContactFieldExtendedAddressValue + item;
		pTempContactItemID->iItemIDCount = 1;
		iContactIdArray.Append(pTempContactItemID);
	}
	
	//Work Address
	for(TInt item = 0;item<5;item++)
	{
		pTempContactItemID = new(ELeave) TContactItemID();
		pTempContactItemID->iMainValue = KUidContactFieldExtendedAddressValue + item;
		pTempContactItemID->iVCardMapPlaceValue = KIntContactFieldVCardMapWORK;
		pTempContactItemID->iItemIDCount = 2;
		iContactIdArray.Append(pTempContactItemID);
	}
	
	//IMs
	for(TInt item = 0;item<6;item++)
	{
		pTempContactItemID = new(ELeave) TContactItemID();
		pTempContactItemID->iMainValue = KUidContactFieldIMAddressValue;
		pTempContactItemID->iItemIDCount = 1;
		iContactIdArray.Append(pTempContactItemID);
	}
	
	//Company
	pTempContactItemID = new(ELeave) TContactItemID();
	pTempContactItemID->iMainValue = KUidContactFieldCompanyNameValue;
	pTempContactItemID->iItemIDCount = 1;
	iContactIdArray.Append(pTempContactItemID);
	
	//Work Position
	pTempContactItemID = new(ELeave) TContactItemID();
	pTempContactItemID->iMainValue = KUidContactFieldPrefixNameValue;
	pTempContactItemID->iItemIDCount = 1;
	iContactIdArray.Append(pTempContactItemID);
	 
	//Other Company
	pTempContactItemID = new(ELeave) TContactItemID();
	pTempContactItemID->iMainValue = KUidContactFieldCompanyNamePronunciationValue;
	pTempContactItemID->iItemIDCount = 1;
	iContactIdArray.Append(pTempContactItemID);
	
	//Other Position
	pTempContactItemID = new(ELeave) TContactItemID();
	pTempContactItemID->iMainValue = KUidContactFieldJobTitleValue;
	pTempContactItemID->iItemIDCount = 1;
	iContactIdArray.Append(pTempContactItemID);
	
	//Nickname
	pTempContactItemID = new(ELeave) TContactItemID();
	pTempContactItemID->iMainValue = KUidContactFieldSecondNameValue;
	pTempContactItemID->iItemIDCount = 1;
	iContactIdArray.Append(pTempContactItemID);
	
	//Website
	pTempContactItemID = new(ELeave) TContactItemID();
	pTempContactItemID->iMainValue = KUidContactFieldUrlValue;
	pTempContactItemID->iItemIDCount = 1;
	iContactIdArray.Append(pTempContactItemID);
	
	//Note
	pTempContactItemID = new(ELeave) TContactItemID();
	pTempContactItemID->iMainValue = KUidContactFieldNoteValue;
	pTempContactItemID->iItemIDCount = 1;
	iContactIdArray.Append(pTempContactItemID);
}

void  ContactEngine::InitializeHeadArray()
{

}



void ContactEngine::ExportContactsWithAPI(const TDesC& aFileName)
{
	RFs fileSession; 
	User::LeaveIfError(fileSession.Connect());
	CleanupClosePushL(fileSession); 
	CContactDatabase* contactDb = CContactDatabase::OpenL();

	CleanupStack::PushL(contactDb);	
	CCntFilter* filter = CCntFilter::NewLC();	
	filter->SetContactFilterTypeALL(EFalse);
    filter->SetContactFilterTypeCard(ETrue);
    contactDb->FilterDatabaseL(*filter); 
    CContactIdArray* exportContact = CContactIdArray::NewL(filter->iIds);
    CleanupStack::PushL(exportContact);  

    RFile file; 
    file.Replace(fileSession,aFileName,EFileWrite);
    CleanupClosePushL(file);  
    RFileWriteStream outputStream(file); 
    CleanupClosePushL(outputStream); 

    TUid id; 
    id.iUid = KVersitEntityUidVCard; 
    contactDb->ExportSelectedContactsL(id,*exportContact, outputStream, CContactDatabase::EExcludeUid); 
    CleanupStack::PopAndDestroy(6);  
}

void  ContactEngine::RefreshContacts()
{
	iContactArray.ResetAndDestroy();	 
	ExportingContactsToArray();
}

Contact* ContactEngine::GetContactByIndex(const TInt aIndex)const
{
	TInt pCount = iContactArray.Count();
	if(pCount == 0)
	{
		return NULL;
		
	}else if(aIndex<0 || aIndex>pCount-1)
	{
		return NULL;
	}else 
	{
		return iContactArray[aIndex];	
	}
}

TInt ContactEngine::GetContactCount()
{
	return iContactArray.Count();
}

void ContactEngine::DeleteContact(const TInt aIndex)
{
	TInt pCount = iContactArray.Count();
	if(pCount == 0)
	{
		return;
	}
	if(aIndex < 0 || aIndex > pCount-1)
	{
		return;
	}
	Contact* pTempContact  = iContactArray[aIndex];
	delete pTempContact;
	iContactArray.Remove(aIndex);
	pCount = iContactArray.Count();
	
//	CContactDatabase* contactDb = CContactDatabase::OpenL();
//	CleanupStack::PushL(contactDb);	
//	Contact* pTempContact = iContactArray[aIndex];	
//	contactDb->DeleteContactL(pTempContact->iContactId);
//	CleanupStack::PopAndDestroy(); 
}

void ContactEngine::ExportContacts(const TDesC& aFileName)
{		
//	RefreshContacts();
	ExportToFile(aFileName);
}

void ContactEngine::ExportToFile(const TDesC& aFileName)
{
	RFs fileSession; 
	User::LeaveIfError(fileSession.Connect());
	CleanupClosePushL(fileSession);
	
	TInt fileSize = 0;
	RFile file; 
	file.Replace(fileSession,aFileName,EFileWrite);
	file.Size(fileSize);	 
	
	if(iHeadText)
	{
		file.Write(fileSize,*iHeadText);
	}
	
	TInt pCount = iContactArray.Count();
	if(pCount == 0)
	{	
		file.Close();
		CleanupStack::PopAndDestroy();  
		return;
	}
	else if(pCount > 0)
	{
		for(TInt item = 0;item<pCount;item++)
		{
			Contact* pTempContact = iContactArray[item];
			if(pTempContact)
			{
				for(TInt item = 0;item<KFieldNumber;item++)
				{		 
					TDesC& pDesC = pTempContact->GetContactFieldByIndex(item);	    
					TInt   pFieldLength = pDesC.Length();
					
					HBufC* pWriteBuf = HBufC::NewL(pFieldLength + KSeprateLength);
					TPtr   pWritePtr(pWriteBuf->Des());
					pWritePtr.Append(pDesC);
					pWritePtr.Append(KContactItemSeprate);
					
					HBufC8* pWriteBuf8 = HBufC8::NewL(3*pWritePtr.Length());
					TPtr8   pWritePtr8(pWriteBuf8->Des());
					
					CnvUtfConverter::ConvertFromUnicodeToUtf8(pWritePtr8,*pWriteBuf);
					
					file.Size(fileSize);
					file.Write(fileSize,pWritePtr8); 
					
					delete pWriteBuf;
					delete pWriteBuf8;		
				}
				file.Size(fileSize);
				file.Write(fileSize,KEnter); 	
				
				if(iExportingNotify)
				{
					iExportingNotify->ExportingNotify(item,pCount);		
				}					
			}	
		}	
	}
	file.Close();
	CleanupStack::PopAndDestroy();  
}


void ContactEngine::ExportASingleContact(Contact& aContact,const TDesC& aFileName)
{
 
	
}

void ContactEngine::ExportingContactsToArray()
{	
	CContactDatabase* contactDb = CContactDatabase::OpenL();
	CleanupStack::PushL(contactDb);	
    
	TContactIter iter(*contactDb); 		
	TContactItemId cardId; 
    TInt count = contactDb->CountL();
    
    TBuf<100> timeBuf;
    
    for(TInt contactItem = 0;contactItem<count;contactItem++)
   	{
   		cardId = iter.NextL();
   		CContactItem* card = contactDb->ReadContactL(cardId);
   		CleanupStack::PushL(card); 
   		CContactItemFieldSet& curset = card->CardFields();
   		TInt FieldCount = curset.Count();	
   		
		if(FieldCount>0)
		{
			 CContactItemField* pItemField = NULL;
			 Contact* pTempContact = Contact::NewL();			 
			 pTempContact->iContactId = cardId;
			 
			 for(TInt item = 0;item<KFieldNumber;item++)
			 {
				 TContactItemID* pTempContactItemID = iContactIdArray[item];	
				 TInt  pItemIDCount = pTempContactItemID->iItemIDCount;
				 
				 for(TInt fieldCountItem = 0;fieldCountItem<FieldCount;fieldCountItem++)
				 {
					 CContactItemField&   pTempItemField = curset[fieldCountItem];
					 const CContentType&  pContectType = pTempItemField.ContentType();
					 TInt pFieldCount = pContectType.FieldTypeCount();
					 
					 if(pFieldCount != pItemIDCount)
					 {
						 continue;
					 }
					 else
					 {
						 if(pFieldCount == 1)
						 {
							 TFieldType pFieldType = pContectType.FieldType(0);	
							 if(pFieldType.iUid == pTempContactItemID->iMainValue)
							 {
								 pItemField = &pTempItemField;
								 SetContactFieldByIndex(pItemField,item,*pTempContact);
								 continue;
							 }
						 }else if(pFieldCount == 2)
						 {
							 TFieldType pMainFieldType = pContectType.FieldType(0);	
							 TFieldType pSecondFieldType = pContectType.FieldType(1);	
							 if( pMainFieldType.iUid  == pTempContactItemID->iMainValue &&
								 pSecondFieldType.iUid  == pTempContactItemID->iVCardMapPropertyValue	 )
							 {
								 pItemField = &pTempItemField;
								 SetContactFieldByIndex(pItemField,item,*pTempContact);
								 continue;
								 
						     }else if( pMainFieldType.iUid  == pTempContactItemID->iMainValue &&
									   pSecondFieldType.iUid  == pTempContactItemID->iVCardMapPlaceValue	 )
								  
							 {
								 pItemField = &pTempItemField;
								 SetContactFieldByIndex(pItemField,item,*pTempContact);
								 continue;							 
							 }							 
						 }else if(pFieldCount == 3)
						 {
							 TFieldType pMainFieldType =   pContectType.FieldType(0);	
							 TFieldType pSecondFieldType = pContectType.FieldType(1);	
							 TFieldType pThirdFieldType =  pContectType.FieldType(2);	
							 
							 if( pMainFieldType.iUid  ==   pTempContactItemID->iMainValue &&
								 pSecondFieldType.iUid  == pTempContactItemID->iVCardMapPropertyValue &&
								 pThirdFieldType.iUid  ==  pTempContactItemID->iVCardMapPlaceValue)
							 {
								 pItemField = &pTempItemField;
								 SetContactFieldByIndex(pItemField,item,*pTempContact);
								 continue;	
							 }
						 }
					 }					
			    }					
			 }//end of KFieldNumber for 			 
			 iContactArray.Append(pTempContact);			 
		}//end of if 
		
		contactDb->CloseContactL(card->Id()); 
		CleanupStack::PopAndDestroy();								 // card 
		
   	}//end of for
    CleanupStack::PopAndDestroy();       
}

void  ContactEngine::SetContactFieldByIndex(CContactItemField* pContactItemField,const TInt aIndex,Contact& pContact)
{
	if(pContactItemField)
	{
		 TStorageType pStorageType = pContactItemField->StorageType();
		 if(pStorageType == KStorageTypeText)					 
		 {
			CContactTextField* pContactTextField = pContactItemField->TextStorage();
			TPtrC  text(pContactTextField->Text().Ptr(),pContactTextField->Text().Length());
			pContact.SetContactFieldByIndex(aIndex,text);
			
		}else if(pStorageType == KStorageTypeDateTime)	
		{
			CContactDateField* pContactDateField = pContactItemField->DateTimeStorage();
			TTime pTime = pContactDateField->Time();	
			TBuf<100> timeBuf;
			timeBuf.Zero();
			pTime.FormatL(timeBuf,_L("%F%Y/%M/%D %H:%T:%S"));  
			pContact.SetContactFieldByIndex(aIndex,timeBuf);
						
		}else if(pStorageType == KStorageTypeStore)
		{
		
			
		}else if(pStorageType == KStorageTypeContactItemId)
		{
			
		}		
		pContactItemField = NULL;
   }
}



void ContactEngine::CheckItemID()
{
	CContactDatabase* contactDb = CContactDatabase::OpenL();
	CleanupStack::PushL(contactDb);	

	TContactIter iter(*contactDb); 		
	TContactItemId cardId; 

	cardId = iter.NextL();
	CContactItem* card = contactDb->ReadContactL(cardId);
	CleanupStack::PushL(card); 
	CContactItemFieldSet& curset = card->CardFields();
	
	TInt FieldCount = curset.Count();
	if(FieldCount > 0)
	{
		for(TInt fieldItem = 0;fieldItem<FieldCount;fieldItem++)
		{
			CContactItemField&   pItemField = curset[fieldItem];
			const CContentType&  pContectType = pItemField.ContentType();
			TInt pFieldCount = pContectType.FieldTypeCount();
			
			HBufC8* writeBuf = HBufC8::NewL(100);
			TPtr8   writePtr(writeBuf->Des());
			
//			writePtr.Append(KFieldText);			
//			TBuf<50>  pFieldText;
//			pItemField.GetFieldText(pFieldText);			
//			writePtr.Append(pFieldText);
//			writePtr.Append(KEnter);
			
			writePtr.Append(KLabel);
			TBuf8<50> tempBuf;
			CnvUtfConverter::ConvertFromUnicodeToUtf8(tempBuf,pItemField.Label());
			writePtr.Append(tempBuf);
			writePtr.Append(KEnter);
			
//			pItemField.SetLabelL(KTestLabel);
			
			if(pFieldCount > 0)
			{
				for(TInt typeItem = 0;typeItem<pFieldCount;typeItem++)
				{
					TFieldType pFieldType = pContectType.FieldType(typeItem);					
#ifdef  WRITE_TO_LOG						
					writePtr.AppendNum(pFieldType.iUid);
					writePtr.Append(KEnter);
#endif
				}				
			}	
			writePtr.Append(KEnter);
			WriteToLog(writePtr);
			delete writeBuf;
		}
	}
}

HBufC8* ContactEngine::ReadHeadText(const TDesC& aFileName)
{
	RFs iFs;
	RFile file;
	TInt nResult = iFs.Connect();
	if(nResult == KErrNone)
	{
		nResult = file.Open(iFs, aFileName, EFileStreamText|EFileRead | EFileShareAny);				 
		if ( nResult == KErrNone)
		{
				TInt fileSize;
				file.Size(fileSize);
				HBufC8* buffer8 = HBufC8::NewL(fileSize);
				TPtr8 ptr8 = buffer8->Des();
				file.Read(ptr8);			 
				file.Close();
				iFs.Close();
				return buffer8;
			}
			else
			{
				iFs.Close();
				return NULL;
			}
		 
	}
	else
	{
		return NULL;
	}
}

#ifdef  WRITE_TO_LOG	
void ContactEngine::WriteToLog(const TDesC8& aDesC)
{

	RFs fileSession; 
	User::LeaveIfError(fileSession.Connect());
	CleanupClosePushL(fileSession);
	
	RFile file; 
	TInt error = file.Open(fileSession,KFileName,EFileWrite);
	CleanupClosePushL(file); 
	
	if(error == KErrNone)
	{
		TInt fileSize;
		file.Size(fileSize);
		file.Write(fileSize,aDesC);
	
	}else 
	{
		file.Replace(fileSession,KFileName,EFileWrite);
		file.Write(aDesC);	
	}
	CleanupStack::PopAndDestroy(2);
}
#endif

//End of file
